//$Revision: 20 $
//$Date: 2012-09-05 00:09:22 +0000 (Wed, 05 Sep 2012) $
//$Author: dev@arbrebinaire.com $
/**
 * @fileOverview
 *
 * Forms utilities
 * Requires:
 * jQuery
 *
 * @author     Francois Hetu <a href="mailto:dev@arbrebinaire.com">dev@arbrebinaire.com</a>
 * @version    SVN: $$Id: forms.js 20 2012-09-05 00:09:22Z dev@arbrebinaire.com $$
 */

var ArbreBinaire = ArbreBinaire || {};
ArbreBinaire.Forms = (function(forms, $){
	var _isMultiSelect = function($field){
			return $field.is('select') && $field.prop('multiple');
		},
		getTextAreaLines = function($textArea){
			return $textArea.val().split('\n');
		},
		setTextAreaLines = function($textArea, answerArr){
			$textArea.val(answerArr.join('\n'));
		},
		/**
		 * Will serialize a form according to jQuery serializeArray() rules except
		 * for multi-selects.  Multi selects will generate a single name/value pair
		 * with ALL options described (be them selected or not)
		 * 
		 * The reverse method is unserializeFormArray
		 * 
		 * @param {jQuery} $form
		 * @return {array} The name/value pairs of the form controls
		 */
		serializeFormArray = function($form){
			var jQuerySerializedValues = $form.serializeArray(),
				serialized = [],
				len = jQuerySerializedValues.length,
				multiSelectList = {},
				$multiSelect = null,
				multiSelectSerializedOptions = [],
				i = 0;
			$('select', $form).each(function(){
				var $el = $(this);
				if($el.prop('multiple')){
					multiSelectList[$el.attr('name')] = $el;	
				}
			});
			for(i; i < len; ++i){
				if(!multiSelectList[jQuerySerializedValues[i]['name']]){
					//Not multi select
					serialized.push(jQuerySerializedValues[i]);
				}
			}
			//The multi-selects
			for(i in multiSelectList){
				if(multiSelectList.hasOwnProperty(i)){
					multiSelectSerializedOptions = [];
					$multiSelect = multiSelectList[i];
					$('option', $multiSelect).each(function(){
						var $option = $(this);
						multiSelectSerializedOptions.push(
							{
								text:        $option.text(),
								value:       $option.attr('value') || '',
								is_selected: $option.prop('selected')
							}
						);
					});
					serialized.push(
						{
							name:  i,
							value: multiSelectSerializedOptions
						}
					);
				}
			}
			return serialized;
		},
		/**
		 * Reverse method of serializeFormArray
		 * 
		 * @param {array} values A name/value pair array as constructed by the method serializeFormArray above
		 * @param {jQuery} $form A jquery form
		 */
		unserializeFormArray = function(values, $form){
			var len = values.length,
				olen = 0,
				optionDefinition = [],
				$field = null,
				$option = null,
				isBool = false,
				optDef = [],
				i = 0, j = 0;
			for(i; i < len; ++i){
				$field = $('[name="' + values[i]['name'] + '"]', $form);
				if(_isMultiSelect($field)){
					//A multi-select: special rule
					optionDefinition = values[i]['value'];
					olen = optionDefinition.length;
					$field.empty();
					for(j = 0; j < olen; ++j){
						optDef = optionDefinition[j];
						isBool = typeof optDef['is_selected'] == 'boolean';
						$option = $('<option>').attr('value', optDef['value']);
						$option.prop('selected', isBool? optDef['is_selected']: optDef['is_selected'] == 'true');
						$option.text(optDef['text']);
						$field.append($option);
					}
				}else{
					$field.val(values[i]['value']);
				}
			}
		};
		
		forms.getTextAreaLines = getTextAreaLines;
		forms.setTextAreaLines = setTextAreaLines;
		forms.serializeFormArray = serializeFormArray;
		forms.unserializeFormArray = unserializeFormArray;
	return forms;
})(ArbreBinaire.Forms || {}, jQuery);